/**
 * Class for performing common operations on an sqlConnection
 */
Flair.Db.Adapter = function () {
	this.connection = null;
	
	/**
	 * Bind function fn's this to scope.
	 *
	 * @param obj scope
	 * @param function fn
	 */
	this.bind = function (scope, fn) {
		return function () { fn.call(scope, arguments); };
	};
	
	/**
	 * Set the connection object for queries
	 *
	 * @param SQLConnection
	 */
	this.setConnection = function (connection) {
		this.connection = connection;
	};
	
	/**
	 * Quote values
	 *
	 * @param string value
	 * @return string
	 */
	this.quote = function (val) {
		// numbers are safe
		if(parseInt(val) == val || parseFloat(val) == val)
			return val;
		var safe = val.replace('\\', '\\\\');
		safe = safe.replace('\'', '\\\'');
		return "'"+safe+"'";
	};
	
	/**
	 * Quote identifiers (field names, table names etc)
	 * 
	 * @param string identifier
	 * @return string
	 */
	this.quoteIdentifier = function (identifier) {
		var safe = identifier.replace('\\', '\\\\');
		safe = safe.replace('\"', '\\\"');
		return safe;		
	};
	
	/**
	 * Run an sql query.
	 * Optionally run asynch by passing a responder 
	 *
	 * @param string sql
	 * @param array params
	 * @param Responder resp
	 */
	this.query = function (sql, params, resp) { 
		var statement = new air.SQLStatement();
		statement.sqlConnection = this.connection;
		statement.text = sql;
		
		if(params)
			for (var i in params)
				statement.parameters[i] = params[i];
		
		if(resp) {
			air.trace('execute w/ responder');
			statement.execute(-1, resp);
		} else 
			statement.execute();
			
		return statement;
	};
	
	/**
	 * Run sql query and fetch all returned records
	 *
	 * @param string sql
	 * @param array params
	 */
	this.fetchAll = function (sql, params, resp) { 
		var stmt = this.query(sql, params, resp);
		if(resp)
			return stmt;
		else
			return this._fetchAll( stmt.getResult() );
	};
	this._fetchAll = function (result) {
		return result.data;
	};
	
	/**
	 * Run sql query and fetch first result record
	 *
	 * @param string sql
	 * @param array params
	 */
	this.fetchRow = function (sql, params, resp) {
		var stmt = this.query(sql, params, resp);
		if(resp)
			return stmt;
		else
			return this._fetchRow( stmt.getResult() );
	};
	this._fetchRow = function (result) {
		if(result.data.length < 1)
			return undefined;
		else return result.data[0];
	};

	/**
	 * Run sql and fetch array of first column values from result records
	 *
	 * @param string sql
	 * @param array params
	 */
	this.fetchCol = function (sql, params, resp) { 
		var stmt = this.query(sql, params, resp);
		if(resp)
			return stmt;
		else 
			return this._fetchCol( stmt.getResult() );
	};
	this._fetchCol = function (result) {
		if(result.data.length < 1)
			return new Array();
		var res = new Array();
		for(var i = 0; i < result.data.length; i++)
			for(var f in result.data[i]) {
				res.push(result.data[i][f]);
				continue;
			}
		return res;
	}
	
	/**
	 * Run sql and fetch first column value of the first result record
	 *
	 * @param string sql
	 * @param array params
	 */
	this.fetchOne = function (sql, params, resp) {
		var stmt = this.query(sql, params, resp);
		if(resp)
			return stmt;
		else 
			return this._fetchOne( stmt.getResult() );
	};
	this._fetchOne = function (result) {
		if(!result.data || result.data.length < 1) {
			return undefined;
		}
		for(var i in result.data[0])
			return result.data[0][i]; // return first match
	}
	
		
	//this._delete = function (table, data, where) {};
	
	/**
	 * Generate and run an insert sql statement from given table and insert data
	 *
	 * @param string table
	 * @param array data
	 */
	this.insert = function (table, data, resp) {
		var sql = "INSERT INTO " + this.quoteIdentifier(table) + " (";
		var dkeys = new Array();
		var values = new Array();
		var placeholders = new Array();
		
		for (var i in data) { 
			dkeys.push(this.quoteIdentifier(i));
			placeholders.push('?');
			values.push(data[i]);
		}
		sql += dkeys.join(', ') + ') VALUES (' + placeholders.join(', ') + ')';
			
		this.query(sql, values, resp);
	};

	/**
	 * Generate and run an update sql statement from given table, update data and where clause
	 *
	 * @param string table
	 * @param array data
	 * @param string where
	 */
	this.update = function (table, data, where, resp) {
		var sql = "UPDATE " + this.quoteIdentifier(table) + " SET ";
		var exprs = new Array();
		var values = new Array();
		
		for (var i in data) { 
			exprs.push(this.quoteIdentifier(i) + ' = ?');
			values.push(data[i]);
		}
		sql += exprs.join(', ');
		
		if(where != undefined)
			sql += ' WHERE ' + where;
			
		this.query(sql, values, resp);
	};
};